package com.antwork.common.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import net.sf.json.JSONObject;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import com.antwork.common.dao.DynamicSqlParameter;
import com.antwork.common.dao.GenericDao;
import com.antwork.common.entity.Pagination;

public abstract class GenericIbatisDao<T, PK extends Serializable> extends
		SqlMapClientDaoSupport implements GenericDao<T, PK> {
	public static final String SQLID_INSERT = "insert";
	public static final String SQLID_UPDATE = "update";
	public static final String SQLID_UPDATE_PARAM = "updateParam";
	public static final String SQLID_DELETE = "delete";
	public static final String SQLID_DELETE_PARAM = "deleteParam";
	public static final String SQLID_TRUNCATE = "truncate";
	public static final String SQLID_SELECT = "select";
	public static final String SQLID_SELECT_PK = "selectPk";
	public static final String SQLID_SELECT_PARAM = "selectParam";
	public static final String SQLID_SELECT_FK = "selectFk";
	public static final String SQLID_COUNT = "count";
	public static final String SQLID_COUNT_PARAM = "countParam";
	private String sqlmapNamespace = "";

	private String dbDialect = "MYSQL";

	public String getSqlmapNamespace() {
		return this.sqlmapNamespace;
	}

	public void setSqlmapNamespace(String sqlmapNamespace) {
		this.sqlmapNamespace = sqlmapNamespace;
	}

	public String getDbDialect() {
		return this.dbDialect;
	}

	public void setDbDialect(String dbDialect) {
		this.dbDialect = dbDialect;
	}

	public int count() {
		Integer count = (Integer) getSqlMapClientTemplate().queryForObject(
				this.sqlmapNamespace + "." + "count");
		return count.intValue();
	}

	public int count(DynamicSqlParameter param) {
		String sqlId = param.getSqlId();
		Integer count;
		if (sqlId == null) {
			count = (Integer) getSqlMapClientTemplate().queryForObject(
					this.sqlmapNamespace + "." + "countParam", param);
		} else {
			getSqlMapClientTemplate().queryForList(
					this.sqlmapNamespace + "." + sqlId, param);
			count = (Integer) getSqlMapClientTemplate().queryForObject(
					this.sqlmapNamespace + "." + sqlId, param);
		}

		return count.intValue();
	}

	public int delete(PK primaryKey) {
		int rows = getSqlMapClientTemplate().delete(
				this.sqlmapNamespace + "." + "delete", primaryKey);
		try {
			getSqlMapClientTemplate().getSqlMapClient().startBatch();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return rows;
	}

	public int delete(DynamicSqlParameter param) {
		int rows = getSqlMapClientTemplate().delete(
				this.sqlmapNamespace + "." + "deleteParam", param);
		return rows;
	}

	public int truncate() {
		int rows = getSqlMapClientTemplate().delete(
				this.sqlmapNamespace + "." + "truncate");
		return rows;
	}

	public T get(PK primaryKey) {
		return (T) getSqlMapClientTemplate().queryForObject(
				this.sqlmapNamespace + "." + "selectPk", primaryKey);
	}

	public void insert(T entity) {
		getSqlMapClientTemplate().insert(this.sqlmapNamespace + "." + "insert",
				entity);
	}

	public T load(PK primaryKey) throws DataAccessException {
		Object o = getSqlMapClientTemplate().queryForObject(
				this.sqlmapNamespace + "." + "selectPk", primaryKey);

		return (T) o;
	}

	public List<T> select() {
		return getSqlMapClientTemplate().queryForList(
				this.sqlmapNamespace + "." + "select");
	}

	public List<T> select(DynamicSqlParameter param) {
		String sqlId = param.getSqlId();
		if (sqlId == null) {
			return getSqlMapClientTemplate().queryForList(
					this.sqlmapNamespace + "." + "selectParam", param);
		}
		return getSqlMapClientTemplate().queryForList(
				this.sqlmapNamespace + "." + sqlId, param);
	}

	public List<T> select(JSONObject param) {
		return getSqlMapClientTemplate().queryForList(
				this.sqlmapNamespace + "." + "selectParam", param);
	}

	public Pagination<T> selectPagination(DynamicSqlParameter param) {
		if (param != null) {
			param.setDbDialect(this.dbDialect);
		}
		String paginationSqlId = param.getPaginationSqlId();

		int count = countForPagination(param);
		Pagination result = new Pagination(param.getPaginationCurrent(),
				param.getPaginationSize(), count);

		if (count > 0) {
			List data = getSqlMapClientTemplate().queryForList(
					this.sqlmapNamespace + "." + paginationSqlId, param);
			result.setResult(data);
		}
		return result;
	}

	private int countForPagination(DynamicSqlParameter param) {
		String paginationCountSqlId = param.getPaginationCountSqlId();
		Integer count = (Integer) getSqlMapClientTemplate().queryForObject(
				this.sqlmapNamespace + "." + paginationCountSqlId, param);
		return count.intValue();
	}

	public List<T> selectFk(DynamicSqlParameter param) {
		return getSqlMapClientTemplate().queryForList(
				this.sqlmapNamespace + "." + "selectFk", param);
	}

	public Pagination<T> selectFkPagination(DynamicSqlParameter param) {
		if (param != null)
			param.setDbDialect(this.dbDialect);
		Pagination result = new Pagination();
		int count = count(param);
		result.setTotalCount(count);
		if (count > 0) {
			List data = getSqlMapClientTemplate().queryForList(
					this.sqlmapNamespace + "." + "selectFk", param);
			result.setResult(data);
		}

		return result;
	}

	public int update(T entity) {
		return getSqlMapClientTemplate().update(
				this.sqlmapNamespace + "." + "update", entity);
	}

	public int update(DynamicSqlParameter param) {
		String sqlId = param.getSqlId();
		if (sqlId == null) {
			return getSqlMapClientTemplate().update(
					this.sqlmapNamespace + "." + "updateParam", param);
		}
		return getSqlMapClientTemplate().update(
				this.sqlmapNamespace + "." + sqlId, param);
	}
}